繼關於後端觀念(五)-關於框架-Express後,接著我們要談關於Express的MVC架構,但在這之前,讓我們先看看MVC的概念。之後,筆者會在講述Node.js的MVC架構,及Express的MVC架構。讓讀者們能理解它們的不同之處。
MVC(Model–view–controller)為軟體工程中的一種軟體架構模式。它由三個部分所形成:
主要用來處理資料的邏輯及資料庫的部分。只要是與資料相關的事情,都會交由它處理。
將Model的資料透過View來呈現給使用者。
藉由使用者的行為來控管及觸發特定的事件,並指示該事件所對應的Model來進行處理。
使用MVC架構的好處就是能協助我們進行程式的維護,這是因為我們賦予程式一個職責分離的設計,使每個程式能夠專心做自己須負責的事情。這不僅利於維護,同時也能讓我們針對各個不同的功能去做測試的動作。試想著,如果我們沒有將程式進行職責分離的動作,這可能會讓單一檔案的程式碼非常的長。若日後發生問題,或是需求改變需要更改特定程式碼...等。眾多例外情況造成維護上或後續開發上的不便。
舉個例子,若今天程式要進行交接的動作,前人所留下來的程式碼又臭又長,且沒有做MVC或職責分離的動作。當你今天要做code review應該會是一件非常痛苦的事情。
註記:MVC之間關係的圖在網路上有非常多的派別,所以筆者這邊就不畫出它們之間的交集圖。且不同的語言或框架其MVC也會有些許不同。當然,釐清他們之前的處理順序固然重要,但最重要還是希望讀者能先知道它們各自負責的項目為何。
在Node.js中的MVC運作會是這樣:
controller
部分來接收request的訊息,並進行剖析的動作。Controller
找出與request所相對應的model
,並將request交由該model
處理。model
處理完後,將資料再交回給controller
,並讓controller
交付給view
做處理。view
產生出能讓client所看到的html檔案,並將其結果轉交給server端。註記:
如果單純只做出API,第5步驟就會變成:Controller
將model
處理完的結果交由server端。
在Express中,若我們使用Express的快速建置開發環境的方式產生Express專案的話,其MVC運作會是這樣:
router
來做處理。router
中。若無則直接對資料進行後處理的動作。router
處理完資料的邏輯後,將其結果傳給view
,並由view
來產生html文件。router
來將view
所產生的html文件送至server端中。註記:
如果單純只做出API,會跳過第4步驟且第5步驟就會變成:
藉由router
將處理完的結果交由server端。
讀者可以發現,藉由Express的快速建置開發環境的專案中,Router
本身就會涵蓋了controller
及model
的部分。
其資料結構會是:
.
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.ejs
└── index.ejs
也就是說我們將controller
及model
的部分都集中寫在routers資料夾底下。假設以routers資料夾中的index.js來說,其程式碼會是:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
// do something
// 連接資料庫
// 從資料庫將資料撈完後進行res.render的動作。
});
module.exports = router;
註記:res.render指Express中,讓處理完的資料傳送到
view
的指令。
若使用Express的快速建置開發環境的專案,是還沒有做到職責分離的動作,我們可以試著將controller
及model
加入其中,其運作會是:
router
的function所接收,並呼叫相對應的controller
。controller
function來呼叫特定的model
做處理。model
中。若無則直接對資料進行後處理的動作。model
處理完資料的邏輯後,將其結果回傳至controller
中。Controller
將model
的資料傳給view
,並由view
來產生html文件。controller
來將view
所產生的html的文件送至server端中。註記:
如果單純只做出API,會跳過第6步驟且第7步驟就會變成:
藉由controller
將model
處理完的結果交由server端。
資料結構就會變成:
.
├── app.js
├── bin
│ └── www
├── controllers
│ ├── index_controller.js
├── models
│ ├── index_model.js
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.ejs
└── index.ejs
也就是我們加入了controllers
及models
的資料夾,並讓底下的js擋來分別負責處理controller
及model
的部分。
其程式碼的部分就會變成:
const IndexController = require('../controllers/index_controller');
indexController = new IndexController();
router.get('/', indexController.sayHiController);
const IndexModel = require('../models/index_model');
indexModel = new IndexModel();
module.exports = class IndexController {
sayHiController(req, res ,next) {
// do something
// 呼叫特定的model
// 從資料庫將資料撈完後進行res.json的動作。
}
}
module.exports = class IndexModel {
sayHiModel(req, res ,next) {
// do something
}
}
藉由上述的介紹,讀者應該對於MVC有更近一步的瞭解了。但筆者提醒「MVC不是一種技術,是一種理念。」MVC的重點在於分化程式的職責,且其運用是非常多元化的。並非今天筆者提出了這種MVC的做法就一定是正確的。今天開發一個專案,專案上要怎麼分化整個程式的職責,其實都是由當時的情況來做考量。且若有一同開發後端的工程師夥伴,就需要跟他們進行溝通,並商榷要用什麼方式來進行開發。
接續,下個分享我們將提及「如何設定資料庫」。
Creating an MVC framework for our Node.js page - getting ready for scalability
樓主好,您文章內的程式碼如下:
const IndexController = require('../controllers/index_controller');
// 以下省略...
這段應該有誤?
應修改為:
const IndexModel = require('../models/index_model'); // <-- 這裏
indexModel = new IndexModel();
module.exports = class IndexController {
sayHiController(req, res ,next) {
// do something
// 呼叫特定的model
// 從資料庫將資料撈完後進行res.json的動作。
}
}
依我理解應該是 controller 需要 import model
這樣對嗎? 剛學 node 不太確定,還講解惑,謝謝~
感謝 singer0503 的抓蟲。
對,這部分的確是我的失誤。
「依我理解應該是 controller 需要 import model」
是的,controller 是要提取 model 裡的 function 資料沒錯。